home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Plug-In Power Pack for Netscape Communicator
/
Plug-In Power Pack for Netscape Communicator.iso
/
plugins
/
dataviews
/
dvtools
/
examples
/
fds
/
fdseval
/
fdseval.c
next >
Wrap
C/C++ Source or Header
|
1997-07-10
|
56KB
|
1,918 lines
#ifndef lint
static char SccsId[]="@(#)FDSeval.c V1.46 6/14/95";
#endif
/*
| file name - FDSeval.c
|===================================================================
|
| copyright (c) 1989, V.I. Corporation
|
| FDSeval.c - Yacc file for expression parser, FDSeval
|
| Alan C Morse 31 may 89
|
|===================================================================
|
| Procedure description/function:
| Contains yacc description for FDSeval, the example
| expression evaluator function data source for DV-Draw
| and DV-Tools.
|
| This parses c-like expression strings, which may get
| arguments from the environment. These arguments
| are denoted in the expression by $n, where n is in
| the range [1-9]. The program works by building a parse
| tree the first time it encounters an expression and
| evaluating the tree every time the select function
| is called for the variable. Nodes in the parse tree
| can reference data source variables, which are read
| each time the expression is evaluated.
|
| Expressions may contain symbols (name strings), which
| define data that is local to the data source. When
| the expressions are parse, the symbols are converted
| to ids and a data area is built for the data source.
| This data area is a linked list of id-value pairs
| (where the ids are INTs and the values are DOUBLEs.)
| As each expression is parsed, the symbol in the expression
| gets translated to an address of the corresponding
| value in the data area.
|
| The data structures are as follows:
|
| STATIC DATA GLOBAL TO THIS MODULE
|
| 1. SymbolNameTable is a symbol table mapping variable names
| to unique numeric ids. Parsing translates all string names
| to unique integers to simplify the structure of the parse
| tree. For example, this means that all variables named "i"
| get replaced with the same id (token) in all expressions.
|
| 2. GlobalEnv contains information about the current expression
| being evaluated. It includes information about the current
| data source or data source variable. It is a (admittedly ugly)
| way of passing contextual information around in case any of
| the evaluation routines need information about who invoked them.
|
| DATA GLOBAL WITHIN A DATASOURCE
|
| 1. DataArea where the values associated with variable names are
| stored. Since the scope of a variable name in an expression is
| the data source that contains it, DataArea must be maintained by
| the data source, not the data source variable. DataArea is
| implemented as a list of id-datum pairs.
|
| DATA TYPES
|
| 1. An expression is a linked list of root parse tree nodes,
| where each root node corresponds to a statement. A parse
| tree node has a value (recalculated every time the tree is
| evaluated, but which may be a constant), a function, and a
| list of parse subtrees.
|
|===================================================================
*/
# include "std.h"
# include "dvstd.h"
# include "FDSeval.h"
# include "dvfds.h"
# include "dvtools.h"
# include "dvtoolfuns.h"
# include "ringbuf.h"
# include "VTmiscfuns.h"
# include "FDSmiscfuns.h"
# include "VIiofuns.h"
# include "MISCfuns.h"
# include "VIstrfuns.h"
# include "Tfundecl.h"
#ifdef RS6000
#ifndef __MATH__
#define __MATH__
#endif
#endif
# include <math.h>
#ifdef RS6000
#ifdef __MATH__
#undef __MATH__
#endif
#endif
LOCAL DOUBLE StringToDouble();
#ifndef ALPHA
long random();
#endif
LOCAL DOUBLE assign(), assign_to_dsv(),
mult(), divide(), add(), minus(), neg(), mod(),
EQtest(), NEtest(), LTtest(), LEtest(), GTtest(), GEtest(),
readsym(), readvar(), cond();
LOCAL VOID GetFcn();
LOCAL FCN fcn;
LOCAL INT numargs;
/*----------------------------------------------------------------*/
/* SYMBOL ID MANAGEMENT ROUTINES */
/*----------------------------------------------------------------*/
typedef INT SYMBOL_ID;
/* The table is a list of symbol ids with corresponding pointers to */
/* data locations, where the DOUBLE value associated with the */
/* name is stored. */
/* There is a global table of symbol-string to symbol-id mappings */
/* This associates a unique 4-byte number with each name, allowing more */
/* compact storage */
/* Convert a symbol string to a symbol id, by looking up the symbol
in a global table of symbol-name-to-id mappings.
*/
LOCAL ADDRESS SymbolNameTable = 0;
LOCAL SYMBOL_ID SymbolIdCounter = 0;
LOCAL SYMBOL_ID ConvertNameToSymbol( symbol_name )
CHAR *symbol_name;
{
ADDRESS hashnode;
/* Make sure the table has been created */
if( (ADDRESS)0 == SymbolNameTable )
SymbolNameTable = VThtcreate( (CHAR*)0, VThtstrconvert,
(VTHTCOMPAREFUNPTR)strcmp );
/* If the symbol is not in the table, add it and give it a unique id */
/* In any case, return its unique id. */
hashnode = VThtkeyfind( SymbolNameTable, symbol_name );
if( hashnode )
return (SYMBOL_ID)VThnvalue( hashnode );
else
{
++SymbolIdCounter; /* Generate a new uniqe symbol id */
VThthninsert( SymbolNameTable,
VIstrclone( symbol_name ), (int*)SymbolIdCounter );
return SymbolIdCounter;
}
}
LOCAL CHAR *ConvertSymbolToName( symbol_id )
SYMBOL_ID symbol_id;
{
ADDRESS hashnode;
/* Make sure the table has been created */
if( (ADDRESS)0 == SymbolNameTable )
return (CHAR*)0; /* Symbol id has no name */
/* If the symbol ID is in the table, */
/* return the string associated with it; */
/* Otherwise, return 0 */
hashnode = VThtvalfind( SymbolNameTable, (ADDRESS)0, (INT*)symbol_id );
if( hashnode )
return (CHAR*)VThnkey( hashnode );
else
return (CHAR*)0;
}
/*----------------------------------------------------------------*/
/* DATA AREA MANAGEMENT ROUTINES */
/*----------------------------------------------------------------*/
/* DataArea types: this is "memory" where data associated with */
/* symbols is stored. */
typedef struct DataAreaEntry
{
struct DataAreaEntry *next;
SYMBOL_ID SymbolId;
DOUBLE DataValue;
} DATA_AREA_ENTRY;
typedef struct
{
DATA_AREA_ENTRY *FirstDataEntry;
} DATA_AREA;
/* Create a data area */
LOCAL DATA_AREA *daCreate()
{
DATA_AREA *NewDataArea;
NewDataArea = (DATA_AREA*)S_ALLOC( sizeof(DATA_AREA) );
NewDataArea->FirstDataEntry = (DATA_AREA_ENTRY*)0;
return NewDataArea;
}
/* Destroy a data area */
LOCAL VOID daDestroy( DataArea )
DATA_AREA *DataArea;
{
DATA_AREA_ENTRY *entry, *next_entry;
for( entry = DataArea->FirstDataEntry, next_entry = (DATA_AREA_ENTRY*)0;
entry;
entry = next_entry )
{
next_entry = entry->next;
S_FREE( (char*)entry );
}
S_FREE( (char*)DataArea );
}
/* Adds an entry to the data area */
LOCAL VOID daAddEntry( DataArea, SymbolId )
DATA_AREA *DataArea;
SYMBOL_ID SymbolId;
{
DATA_AREA_ENTRY *new_entry, *entry;
for( entry = DataArea->FirstDataEntry; entry; entry = entry->next )
{
if( entry->SymbolId == SymbolId )
return; /* Symbol is already in the list */
}
/* If we get here, entry is not in the list. */
new_entry = (DATA_AREA_ENTRY*)S_ALLOC( sizeof(DATA_AREA_ENTRY) );
/* Add entry to the beginning of the list */
new_entry->next = DataArea->FirstDataEntry;
new_entry->SymbolId = SymbolId;
new_entry->DataValue = 0.0;
DataArea->FirstDataEntry = new_entry;
}
/* Gets address of datum associated with a given symbol id */
LOCAL DOUBLE DummyValue = 0;
LOCAL DOUBLE* daGetDatumAddress( DataArea, SymbolId )
DATA_AREA *DataArea;
SYMBOL_ID SymbolId;
{
DATA_AREA_ENTRY *entry;
for( entry = DataArea->FirstDataEntry; entry; entry = entry->next )
{
if( entry->SymbolId == SymbolId )
return &entry->DataValue;
}
return (DOUBLE*)&DummyValue;
}
/* ---------------------------------------------------------------*/
/* PARSE TREE NODE TYPE DEFINITION */
/* ---------------------------------------------------------------*/
/* Each expression generates a linked list of parse trees, which */
/* are evaluated sequentially. */
#define MAX_SUBTREES 3
typedef struct ParseTreeNode
{
DOUBLE value;
FCN fcn;
ADDRESS params;/* Parameter area for use by function, fcn. Memory
| is allocated by fcn, but freed by PTNdestroy. This data area
| allows the function to maintain state information from one
| call to the next. */
VOID (*FreeParams)(); /* Function for freeing the parameter area */
struct ParseTreeNode *Subtree[MAX_SUBTREES];
} NODE;
typedef struct expstruct
{
struct expstruct *next;
NODE *exp;
} EXPRESSION;
LOCAL NODE *PTNcreate();
LOCAL VOID PTNdestroy();
LOCAL DOUBLE PTNeval();
#ifdef DEBUG
LOCAL VOID PTNprint();
#endif
/*---------------------------------------------------------------*/
/* Parameter area for the eval function data source */
/*---------------------------------------------------------------*/
typedef struct
{
EXPRESSION *read_explist;/* Exp list to be evaluated by read every time. */
DATA_AREA *data_area; /* Where data associated with symbols is kept */
} EVAL_PARAMS;
LOCAL EVAL_PARAMS *CurrentParams;
/* ---------------------------------------------------------------*/
#ifdef YYDEBUG
LOCAL DV_BOOL debug = YES;
#else
LOCAL DV_BOOL debug = NO;
#endif
LOCAL DOUBLE number;
LOCAL NODE *ParseResult = 0;
LOCAL CHAR id[30];
LOCAL INT CurrentArgIndex;
/* Global variable giving contextual information of the expression */
/* that is being evaluated */
LOCAL struct
{
NODE* CurrentNode; /* Current node in parse tree */
V_FDS_FCN_ENUM FdsFunType; /* Type of fds function */
/* that invoked evaluation */
CHAR *CurrentFunction; /* Name of type of invoking fds function */
} GlobalEnv;
typedef union
{
NODE *Nval;
double dval;
int ival;
SYMBOL_ID Sval;
FCN Fval;
ADDRESS Aval;
} YYSTYPE;
# define EXPR_ARG_MARKER 257
# define ID 258
# define EVAL_NUMBER 259
# define TERMINATOR 260
# define INCLUDE_FILE 261
# define EQ 262
# define NE 263
# define LE 264
# define GE 265
# define LT 266
# define GT 267
# define NEG 268
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern int yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256
#include "FDSevallex.h"
/* -------------------------------------------------------------*/
/* Conversion routines */
/* -------------------------------------------------------------*/
LOCAL DOUBLE StringToDouble( s )
CHAR *s;
{
DOUBLE number = 0;
if( 1 != S_SSCANF( s, "%lf", &number ) )
number = 0;
return number;
}
/* -------------------------------------------------------------*/
/* Error Handling and echoing functions */
/* -------------------------------------------------------------*/
/* Local routine to print an error string, specifying the */
/* datasource and dsvar in which it occurred. */
LOCAL void PrintErrString( errstring )
CHAR *errstring;
{
/* What and where of error message */
(VOID)S_FPRINTF( stderr,"FDSeval: %s (DS: %s",
errstring, TdsGetName(M_dscurrent) );
if( M_dsvcurrent )
/* Error is in select function of dsvar */
(VOID)S_FPRINTF( stderr,", DSV: %s)\n", TdsvGetName(M_dsvcurrent) );
else
/* Error is in open or read for ds */
(VOID)S_FPRINTF( stderr,": %s)\n", GlobalEnv.CurrentFunction );
}
LOCAL void yyerror( errstring )
CHAR *errstring;
{
CHAR c;
CHAR *substart, *subend; /* Subexpression start and end */
INT err_offset; /* Number of characters from beginning or expression
where error occurs. */
PrintErrString( errstring );
/* Find the portion of the string that contains the error */
/* by locating the beginning and ending of the current expression. */
substart = subend = expression;
err_offset = 0;
while( substart != ExpStart && *substart != '\n' )
{ substart--; err_offset++; }
if( *substart == '\n' ) substart++;
while( *subend != '\0' && *subend != '\n' && *subend != ';' )
subend++;
/* Echo the expression */
c = *subend;
*subend = '\0';
(VOID)S_FPRINTF( stderr," %s\n", substart );
*subend = c;
/* Place marker indicating approximate position of error */
for( ; err_offset > 0; err_offset-- )
(VOID)S_FPRINTF( stderr, " " );
(VOID)S_FPRINTF( stderr, "^^^\n" );
}
LOCAL VOID ErrFcnUndefined( FcnNameId )
SYMBOL_ID FcnNameId;
{
CHAR msg[128];
CHAR *FcnName;
FcnName = ConvertSymbolToName( FcnNameId );
if( FcnName )
{
S_SPRINTF( msg, "Function %s undefined.", FcnName );
yyerror( msg );
}
}
LOCAL VOID ErrArgMismatch( FcnNameId, NumArgsExpected, ActualNumArgs )
SYMBOL_ID FcnNameId;
INT NumArgsExpected, ActualNumArgs;
{
CHAR msg[128];
CHAR *FcnName;
FcnName = ConvertSymbolToName( FcnNameId );
if( FcnName )
{
S_SPRINTF( msg,
"Wrong number of arguments for %s; expected %d, got %d.",
FcnName, NumArgsExpected, ActualNumArgs );
yyerror( msg );
yyerror( "Function call replaced with a constant zero." );
}
}
/*--------------------------------------------------------------*/
/* Get a function from the table */
/*--------------------------------------------------------------*/
typedef struct
{
CHAR *name;
FCN fcn;
INT numargs;
} FUN_DESC;
#include "FDSevalfuns.h" /* Function definitions and table setup */
LOCAL VOID GetFcn( name, fcn, numargs )
SYMBOL_ID name;
FCN *fcn;
INT *numargs;
{
INT i;
*numargs = 0;
*fcn = (FCN)0;
for( i=0; i<NUMFCNS; i++ )
if( name == ConvertNameToSymbol( FcnTable[i].name ) )
{
*fcn = FcnTable[i].fcn;
*numargs = FcnTable[i].numargs;
return;
}
}
CHAR *GetFcnName( fcn )
FCN fcn;
{
INT i;
for( i=0; i<NUMFCNS; i++ )
if( fcn == FcnTable[i].fcn ) return FcnTable[i].name;
return (CHAR*)0;
}
/*--------------------------------------------------------------*/
/* Functions for use in expressions */
/*--------------------------------------------------------------*/
LOCAL DOUBLE mult( a, b ) DOUBLE a,b; { return a * b; }
LOCAL DOUBLE divide( a, b )
DOUBLE a,b;
{
if( b != 0.0 )
return (a/b);
else
{
PrintErrString("Divide by zero");
return 0.0;
}
}
LOCAL DOUBLE add( a, b ) DOUBLE a,b; { return a + b; }
LOCAL DOUBLE mod( a, b ) DOUBLE a,b; { return (DOUBLE)((INT)a % (INT)b);}
LOCAL DOUBLE minus( a, b ) DOUBLE a,b; { return a - b; }
LOCAL DOUBLE neg( a ) DOUBLE a; { return -a; }
LOCAL DOUBLE EQtest( a, b ) DOUBLE a,b; { return (a == b) ? 1 : 0; }
LOCAL DOUBLE NEtest( a, b ) DOUBLE a,b; { return (a != b) ? 1 : 0; }
LOCAL DOUBLE LTtest( a, b ) DOUBLE a,b; { return (a < b) ? 1 : 0; }
LOCAL DOUBLE LEtest( a, b ) DOUBLE a,b; { return (a <= b) ? 1 : 0; }
LOCAL DOUBLE GTtest( a, b ) DOUBLE a,b; { return (a > b) ? 1 : 0; }
LOCAL DOUBLE GEtest( a, b ) DOUBLE a,b; { return (a >= b) ? 1 : 0; }
LOCAL DOUBLE cond( a, b, c ) DOUBLE a,b,c; { return (a != 0) ? b : c; }
/*---------------------------------------------------------------- */
/* Assigns the value of an expression to an address
ASSUMES the GlobalEnv.CurrentNode->params has the destination address
*/
LOCAL DOUBLE assign( a )
DOUBLE a;
{
if( GlobalEnv.CurrentNode->params )
*((DOUBLE*)GlobalEnv.CurrentNode->params) = a;
return a;
}
/*---------------------------------------------------------------- */
/* Assigns the value of an expression into a dsvar's data area
ASSUMES the GlobalEnv.CurrentNode->params has the argument index
argindex of the destination dsv
*/
LOCAL DOUBLE assign_to_dsv( a )
DOUBLE a;
{
if( GlobalEnv.CurrentNode->params )
{
DV_BOOL result;
INT argindex, argtype;
ANYTYPE arg;
/* If the argindex refers to a data source variable, then assign */
/* the value to it. */
argindex = (INT)GlobalEnv.CurrentNode->params;
/* Get the argindex-th argument */
switch( GlobalEnv.FdsFunType )
{
case V_FDS_FCN_OPEN:
case V_FDS_FCN_READ:
result = TdsGetFcnArg( M_dscurrent, GlobalEnv.FdsFunType, argindex+1,
&argtype, &arg );
break;
case V_FDS_FCN_SELECT:
result = TdsvGetFcnArg( M_dsvcurrent, GlobalEnv.FdsFunType, argindex+1,
&argtype, &arg );
break;
default:
return (DOUBLE)0;
}
if( result == DV_SUCCESS && argtype == V_DSV_TYPE )
TdsvSetValue( arg.ptr, a, 0, 0 );
}
return a;
}
/*---------------------------------------------------------------- */
/* Reads the value of a symbol
ASSUMES the GlobalEnv.CurrentNode->params has the symbol value's address
*/
LOCAL DOUBLE readsym()
{
if( GlobalEnv.CurrentNode->params )
return *((DOUBLE*)GlobalEnv.CurrentNode->params);
else return 0;
}
/*---------------------------------------------------------------- */
/* Gets the value from a data source variable or other FDS arg
Assumes the parameter field has been setup with the argument
index. This must resolve the argument each time in case users
have rebound the data source arguments.
*/
LOCAL DOUBLE readvar()
{
DV_BOOL result;
INT argindex, argtype;
ANYTYPE arg;
argindex = (INT)GlobalEnv.CurrentNode->params;
switch( GlobalEnv.FdsFunType )
{
case V_FDS_FCN_OPEN:
case V_FDS_FCN_READ:
result = TdsGetFcnArg( M_dscurrent, GlobalEnv.FdsFunType, argindex+1,
&argtype, &arg );
break;
case V_FDS_FCN_SELECT:
result = TdsvGetFcnArg( M_dsvcurrent, GlobalEnv.FdsFunType,argindex+1,
&argtype, &arg );
break;
default:
return (DOUBLE)0;
}
if( result == DV_SUCCESS )
{
INT datatype;
ADDRESS databuf;
switch( argtype )
{
case V_DSV_TYPE: /* Argument is a data source variable */
databuf = TdsvGetBuffer( arg.ptr );
datatype = TdsvGetType( arg.ptr );
/* Read its data buffer, looking at its type */
switch( datatype )
{
case V_C_TYPE: return (DOUBLE)(*(CHAR*)databuf);
case V_UC_TYPE: return (DOUBLE)(*(UBYTE*)databuf);
case V_S_TYPE: return (DOUBLE)(*(SHORT*)databuf);
case V_US_TYPE: return (DOUBLE)(*(USHORT*)databuf);
case V_L_TYPE: return (DOUBLE)(*(LONG*)databuf);
case V_UL_TYPE: return (DOUBLE)(*(ULONG*)databuf);
case V_F_TYPE: return (DOUBLE)(*(FLOAT*)databuf);
case V_D_TYPE: return *(DOUBLE*)databuf;
case V_T_TYPE: return StringToDouble((CHAR*)databuf);
}
case V_L_TYPE: /* Argument is a long constant */
return (DOUBLE)arg.l;
case V_D_TYPE: /* Argument is a double constant */
return (DOUBLE)arg.d;
case V_T_TYPE: /* Argument is a string constant */
/* Try to read the string as a double */
return StringToDouble(arg.ptr);
default:
case V_NULL_TYPE: /* Unknown or null argument */
return (DOUBLE)0;
}
}
return (DOUBLE)0;
}
/*--------------------------------------------------------------*/
/* Parse tree handling functions */
/*--------------------------------------------------------------*/
/*
| Module description/function:
|
| These routines manage the creation, traversal and
| destruction of an expression parse tree. A parse tree
| is a linked set of parse tree nodes (PTN), where each node
| has a function for evaluating the value of the node,
| which takes the value of up to MAX_SUBTREES subtree nodes
| as arguments.
|
| ------------------------------------------------------------------
| Module contents:
| Name Description
| ------- -------------------------------
| PTNcreate Creates a new parse tree node
| PTNdestroy Destroys a parse tree node and all its subnodes.
| PTNeval Get the value of a parse tree node.
| PTNsetParam Set parameter field for node.
| PTNgetParam Get parameter field for node.
#ifdef DEBUG
| PTNprint Print a subtree
#endif
|
|====================================================================
*/
/*-----------------------------------------------------------------*/
LOCAL NODE *PTNcreate( value, fcn, sub1, sub2, sub3 )
DOUBLE value;
FCN fcn;
NODE *sub1, *sub2, *sub3;
{
NODE *new;
new = (NODE*)S_ALLOC( sizeof(NODE) );
new->value = value;
new->fcn = fcn;
new->params = (ADDRESS)0;
new->FreeParams = (VOID(*)())0;
/* Assign the subtree arguments */
new->Subtree[0] = sub1;
new->Subtree[1] = sub2;
new->Subtree[2] = sub3;
return new;
}
/*-----------------------------------------------------------------*/
LOCAL VOID PTNdestroy( ptn )
NODE *ptn;
{
if( ptn->params && ptn->FreeParams)
(*ptn->FreeParams)( ptn->params );
if( ptn->Subtree[0] ) PTNdestroy( ptn->Subtree[0] );
if( ptn->Subtree[1] ) PTNdestroy( ptn->Subtree[1] );
if( ptn->Subtree[2] ) PTNdestroy( ptn->Subtree[2] );
S_FREE( (ADDRESS)ptn );
}
/*-----------------------------------------------------------------*/
LOCAL DOUBLE PTNeval( ptn )
NODE *ptn;
{
INT i;
DOUBLE r[MAX_SUBTREES];
if( ptn->fcn )
{
/* Handle the conditional expression (exp?exp:exp) as a special case */
/* Only evaluate the subtrees if it is necessary. */
if( ptn->fcn == cond )
{
/* For a conditional function, evaluate the "if" part (the condition) */
/* and then evaluate the appropriate "then" or "else" subtree. */
if( 0.0 != PTNeval( ptn->Subtree[0] ) )
ptn->value = PTNeval( ptn->Subtree[1] ); /* True part */
else
ptn->value = PTNeval( ptn->Subtree[2] ); /* False part */
}
else
{ /* Not a conditional expression */
/* Evaluate each relevant subtree */
for( i=0; i<MAX_SUBTREES; i++ )
if( ptn->Subtree[i] )
r[i] = PTNeval( ptn->Subtree[i] );
else
break;
/* Set global variable that defines the current node */
GlobalEnv.CurrentNode = ptn;
/* Evaluate the function */
switch( i )
{
case 0: ptn->value = (*ptn->fcn)(); break;
case 1: ptn->value = (*ptn->fcn)( r[0] ); break;
case 2: ptn->value = (*ptn->fcn)( r[0],r[1] ); break;
case 3: ptn->value = (*ptn->fcn)( r[0],r[1],r[2] ); break;
case 4: ptn->value = (*ptn->fcn)( r[0],r[1],r[2],r[3] ); break;
};
}
}
return ptn->value;
}
/*-----------------------------------------------------------------*/
#ifdef DEBUG
LOCAL VOID PTNprint( ptn, depth )
NODE *ptn;
INT depth;
{
INT i;
for( i=depth; i>0; i-- ) (VOID)S_PRINTF( " | " );
(VOID)S_PRINTF( "Node: 0x%x; Value: %f; Function: 0x%x (%s)\n",
ptn, ptn->value, ptn->fcn, GetFcnName(ptn->fcn) );
for( i=0; i<MAX_SUBTREES; i++ )
if( ptn->Subtree[i] ) PTNprint( ptn->Subtree[i], depth+1 );
}
#endif
/*--------------------------------------------------------------*/
/* FUNCTION DATA SOURCE for expression evaluation */
/*--------------------------------------------------------------*/
GLOBALREF ADDRESS M_dsvcurrent;
GLOBALREF ADDRESS M_dscurrent;
/*--------------------------------------------------------------*/
/* ExpListCreate */
LOCAL EXPRESSION* ExpListCreate( exp )
CHAR *exp;
{
INT slen;
EXPRESSION *ElistStart = 0, *Enode;
DV_INIT( Enode, (EXPRESSION *)0 );
/*
The expression to be parsed is passed to the parser
using static variables:
expression is a (CHAR*) that steps through the string.
ExpStart points to the start of the string.
ParseResult gets the result of the parse
CurrentParams has other info, including the symbol table.
*/
/* Allocate a string and add the terminator character ';' */
slen = S_STRLEN( exp );
ExpStart = S_ALLOC( (slen+2) * (LONG)sizeof(CHAR) );
(VOID)S_STRNCPY( ExpStart, exp, slen );
ExpStart[slen] = ';';
ExpStart[slen+1] = '\0';
expression = ExpStart;
while( *expression )
{
ParseResult = 0;
if( 0 == yyparse() )
{
if( ParseResult )
{ /* We have a valid parse tree */
if( ElistStart == 0 )
/* Start the list */
Enode = ElistStart = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
else
{ /* Add it to the end of the current list */
Enode->next = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
Enode = Enode->next;
}
Enode->next = (struct expstruct*)0;
Enode->exp = ParseResult;
}
/* else; No parse tree generated for this part of the expression */
}
else
{ /* Parse failed; create a '0' generator, if no expression so far */
if( ParseResult ) PTNdestroy( ParseResult );
if( ElistStart == 0)
{
ElistStart = (EXPRESSION*)S_ALLOC( sizeof(EXPRESSION) );
ElistStart->next = (struct expstruct*)0;
ElistStart->exp =
PTNcreate( (DOUBLE)0,(FCN)0,(NODE*)0,(NODE*)0,(NODE*)0 );
}
break;
}
}
S_FREE( (ADDRESS)ExpStart );
return ElistStart;
}
/*--------------------------------------------------------------*/
/* Destroy an expression list */
LOCAL VOID ExpListDestroy( ExpList )
EXPRESSION *ExpList; /* Linked list of expressions */
{
EXPRESSION *ExpNext;
while( ExpList )
{
ExpNext = ExpList->next;
PTNdestroy( ExpList->exp );
S_FREE( (ADDRESS)ExpList );
ExpList = ExpNext;
}
}
/*--------------------------------------------------------------*/
/* Evaluate and expression list */
LOCAL VOID ExpListEval( ExpList )
EXPRESSION *ExpList; /* Linked list of expressions */
{
/* Evaluate each expression. The data source ends up with the result */
/* of the last expression. */
for( ; ExpList; ExpList = ExpList->next )
TdsvSetValue( M_dsvcurrent, (DOUBLE)PTNeval(ExpList->exp), 0, 0 );
}
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
LOCAL LONG evalinit V_P_ ((CHAR *, V_FDS_OPT_ARG *));
V_FDS_FCN_DECL( V_FDS_FCN_OPEN, evalinitdesc, evalinit, "Initialize" )
V_FDS_TEXT_ARG_DECL( "Initial eqs", "i=0" )
V_FDS_END_FCN_DECL
LOCAL LONG evalinit( exp, opt_args )
CHAR *exp;
V_FDS_OPT_ARG *opt_args;
{
EVAL_PARAMS *ep;
EXPRESSION *ExpList, *Enode;
#ifndef RS6000
#ifndef DV_DEV_COMP
int strcmp();
#endif
#endif
ep = (EVAL_PARAMS*)S_ALLOC( sizeof(EVAL_PARAMS) );
if( ep == NULL ) return DV_FAILURE;
ep->read_explist = 0; /* Common expression list to be evaluated by read */
ep->data_area = daCreate();
(VOID)TdsSetAuxData( M_dscurrent, (ADDRESS)ep, (TDSFREEFUNPTR)0 );
/* If there is an initialization expression, evaluate it */
/* The evaluation primes the symbol table as a side effect */
if( exp )
{
CurrentParams = ep;
/* Set up part of global env that describes what invoked evaluation */
GlobalEnv.FdsFunType = V_FDS_FCN_OPEN;
GlobalEnv.CurrentFunction = "Data Source OPEN";
/* Parse the expression */
ExpList = ExpListCreate( exp );
/* Evaluate the expression */
for( Enode = ExpList; Enode; Enode = Enode->next )
(VOID)PTNeval(Enode->exp);
ExpListDestroy( ExpList );
}
return DV_SUCCESS;
}
/*--------------------------------------------------------------*/
LOCAL VOID evalterm V_P_ ((void));
V_FDS_FCN_DECL( V_FDS_FCN_CLOSE, evaltermdesc, evalterm, "Terminate" )
V_FDS_END_FCN_DECL
LOCAL VOID evalterm()
{
EVAL_PARAMS *ep;
ep = (EVAL_PARAMS*)TdsGetAuxData( M_dscurrent );
if( ep->read_explist )
ExpListDestroy( ep->read_explist );
daDestroy( ep->data_area );
S_FREE((ADDRESS)ep);
}
/*--------------------------------------------------------------*/
LOCAL LONG evalread V_P_ ((CHAR *, V_FDS_OPT_ARG *));
V_FDS_FCN_DECL( V_FDS_FCN_READ, evalreaddesc, evalread, "Read" )
V_FDS_TEXT_ARG_DECL( "Update eqs", "i=i+1" )
V_FDS_END_FCN_DECL
LOCAL LONG evalread( exp, opt_args )
CHAR *exp;
V_FDS_OPT_ARG *opt_args;
{
EXPRESSION *Enode;
/* Set up part of global environment that describes */
/* what invoked the evaluation */
GlobalEnv.FdsFunType = V_FDS_FCN_READ;
GlobalEnv.CurrentFunction = "Data Source READ";
CurrentParams = (EVAL_PARAMS*)TdsGetAuxData( M_dscurrent );
if( exp && CurrentParams->read_explist == NULL )
{
/* Parse the expression */
CurrentParams->read_explist = ExpListCreate( exp );
}
/* Evaluate the expression */
for( Enode = CurrentParams->read_explist; Enode; Enode = Enode->next )
(VOID)PTNeval(Enode->exp);
/* always return SUCSSESS, DV_FAILURE means to simulate an EOF */
return DV_SUCCESS;
}
/*--------------------------------------------------------------*/
/* FDS SELECT functions */
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
/* EvalString - String expression evaluator */
/*
The argument is an expression string followed by a number of
values that replace parts of the string. This supports optional
arguments of type expr_arg, which replace symbols of the form $n,
where n is in the range [0-9].
*/
LOCAL LONG EvalString V_P_ ((CHAR *, V_FDS_OPT_ARG *));
V_FDS_FCN_DECL( V_FDS_FCN_SELECT, evaldesc, EvalString, "Eval String" )
V_FDS_TEXT_ARG_DECL( "expression", "wnoise()" )
V_FDS_END_FCN_DECL
LOCAL LONG EvalString( exp, opt_args )
CHAR *exp;
V_FDS_OPT_ARG *opt_args;
{
EXPRESSION *ExpList;
/* If this is the first time that the routine has been called */
/* then parse the expressions and save the parse trees */
ExpList = (EXPRESSION*)TdsvGetAuxData( M_dsvcurrent );
if( ExpList == NULL )
{
/* Parse the expression and save it with the data source. */
ExpList = ExpListCreate( exp );
if( ExpList )
(VOID)TdsvSetAuxData( M_dsvcurrent,
(ADDRESS)ExpList, (TDSFREEFUNPTR)ExpListDestroy );
}
/* Set up part of global environment that describes */
/* what invoked the evaluation */
GlobalEnv.FdsFunType = V_FDS_FCN_SELECT;
ExpListEval( ExpList );
/* always return DV_SUCCESS, DV_FAILURE would simulate an EOF */
return DV_SUCCESS;
}
/*--------------------------------------------------------------*/
/* GetDsvValue - Gets value from a data source into a symbol */
LOCAL LONG GetDsvValue V_P_ ((CHAR *, ADDRESS, ADDRESS));
V_FDS_FCN_DECL( V_FDS_FCN_SELECT, getdsvdesc, GetDsvValue,
"Read Data Source Value" )
V_FDS_TEXT_ARG_DECL( "expression", "$1 + $2" )
V_FDS_DSVAR_ARG_DECL( "Value $1" )
V_FDS_DSVAR_ARG_DECL( "Value $2" )
V_FDS_END_FCN_DECL
LOCAL LONG GetDsvValue( exp, dsvar1, dsvar2 )
CHAR *exp;
ADDRESS dsvar1, dsvar2;
{
EXPRESSION *ExpList;
/* If this is the first time that the routine has been called */
/* then parse the expressions and save the parse trees */
ExpList = (EXPRESSION*)TdsvGetAuxData( M_dsvcurrent );
if( ExpList == NULL )
{
ExpList = ExpListCreate( exp );
if( ExpList )
(VOID)TdsvSetAuxData( M_dsvcurrent,
(ADDRESS)ExpList, (TDSFREEFUNPTR)ExpListDestroy );
}
/* Set up part of global environment that describes */
/* what invoked the evaluation */
GlobalEnv.FdsFunType = V_FDS_FCN_SELECT;
ExpListEval( ExpList );
/* always return SUCSSESS, DV_FAILURE means to simulate an EOF */
return DV_SUCCESS;
}
/*--------------------------------------------------------------*/
V_FDS_START_DECL( FDSeval )
V_FDS_FCN_DEFINED( evalinitdesc )
V_FDS_FCN_DEFINED( evaltermdesc )
V_FDS_FCN_DEFINED( evalreaddesc )
V_FDS_FCN_DEFINED( evaldesc )
V_FDS_FCN_DEFINED( getdsvdesc )
V_FDS_END_DECL
int yyexca[] ={
-1, 1,
0, -1,
-2, 0,
};
# define YYNPROD 31
# define YYLAST 311
int yyact[]={
26, 28, 27, 25, 57, 23, 21, 58, 22, 26,
24, 29, 7, 53, 23, 21, 54, 22, 31, 24,
8, 1, 0, 26, 0, 10, 14, 60, 23, 21,
9, 22, 26, 24, 0, 14, 26, 23, 21, 30,
22, 0, 24, 0, 0, 0, 26, 0, 0, 14,
51, 23, 21, 52, 22, 26, 24, 25, 14, 26,
23, 21, 0, 22, 23, 24, 25, 0, 26, 24,
10, 49, 14, 23, 21, 9, 22, 26, 24, 0,
25, 14, 23, 21, 0, 22, 0, 24, 0, 25,
0, 10, 26, 25, 14, 0, 9, 23, 21, 0,
22, 0, 24, 25, 0, 0, 0, 0, 0, 0,
0, 0, 25, 0, 0, 0, 25, 0, 0, 0,
3, 0, 0, 0, 0, 25, 0, 0, 0, 0,
32, 33, 0, 0, 25, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 0, 25,
47, 48, 50, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 55, 0, 56, 0, 0, 0, 59,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 16, 15, 19, 17, 20,
18, 0, 0, 0, 16, 15, 19, 17, 20, 18,
0, 5, 11, 12, 6, 2, 4, 0, 16, 15,
19, 17, 20, 18, 0, 0, 0, 16, 15, 19,
17, 20, 18, 0, 0, 0, 0, 0, 0, 0,
0, 16, 15, 19, 17, 20, 18, 0, 13, 0,
16, 15, 19, 17, 20, 18, 0, 11, 12, 6,
0, 0, 0, 16, 15, 19, 17, 20, 18, 0,
0, 0, 0, 0, 19, 17, 20, 18, 11, 12,
6 };
int yypact[]={
-15, -1000, -1000, 18, -258, -259, -1000, -50, -22, 51,
51, -1000, -1000, -1000, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, -1000, -1000, 51,
51, 30, -91, 9, -5, 40, 40, 55, 55, 55,
55, 22, 22, -1, -1, -91, -91, 31, 31, -1000,
-28, -1000, 51, -1000, 51, 31, -37, -1000, 51, -14,
-1000 };
int yypgo[]={
0, 21, 120, 20, 12 };
int yyr1[]={
0, 1, 1, 1, 1, 3, 4, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2 };
int yyr2[]={
0, 3, 5, 5, 5, 3, 3, 3, 3, 7,
7, 11, 7, 9, 13, 17, 3, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 5, 7, 7,
7 };
int yychk[]={
-1000, -1, 260, -2, 261, 256, 259, -4, -3, 45,
40, 257, 258, 260, 63, 263, 262, 265, 267, 264,
266, 43, 45, 42, 47, 94, 37, 260, 260, 61,
61, 40, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, 41,
-2, 41, 58, 41, 44, -2, -2, 41, 44, -2,
41 };
int yydef[]={
0, -2, 1, 0, 0, 0, 7, 8, 16, 0,
0, 6, 5, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 3, 4, 0,
0, 0, 27, 0, 0, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 28, 29, 10, 9, 12,
0, 30, 0, 13, 0, 11, 0, 14, 0, 0,
15 };
typedef struct { char *t_name; int t_val; } yytoktype;
#ifndef YYDEBUG
# define YYDEBUG 0 /* don't allow debugging */
#endif
#if YYDEBUG
yytoktype yytoks[] =
{
"EXPR_ARG_MARKER", 257,
"ID", 258,
"EVAL_NUMBER", 259,
"TERMINATOR", 260,
"INCLUDE_FILE", 261,
"EQ", 262,
"NE", 263,
"LE", 264,
"GE", 265,
"LT", 266,
"GT", 267,
"=", 61,
"?", 63,
":", 58,
"+", 43,
"-", 45,
"*", 42,
"/", 47,
"%", 37,
"!", 33,
"NEG", 268,
"^", 94,
"-unknown-", -1 /* ends search */
};
char * yyreds[] =
{
"-no such reduction-",
"stmt : TERMINATOR",
"stmt : exp TERMINATOR",
"stmt : INCLUDE_FILE TERMINATOR",
"stmt : error TERMINATOR",
"symbol : ID",
"arg : EXPR_ARG_MARKER",
"exp : EVAL_NUMBER",
"exp : arg",
"exp : symbol '=' exp",
"exp : arg '=' exp",
"exp : exp '?' exp ':' exp",
"exp : symbol '(' ')'",
"exp : symbol '(' exp ')'",
"exp : symbol '(' exp ',' exp ')'",
"exp : symbol '(' exp ',' exp ',' exp ')'",
"exp : symbol",
"exp : exp NE exp",
"exp : exp EQ exp",
"exp : exp GE exp",
"exp : exp GT exp",
"exp : exp LE exp",
"exp : exp LT exp",
"exp : exp '+' exp",
"exp : exp '-' exp",
"exp : exp '*' exp",
"exp : exp '/' exp",
"exp : '-' exp",
"exp : exp '^' exp",
"exp : exp '%' exp",
"exp : '(' exp ')'",
};
#endif /* YYDEBUG */
/* @(#)yaccpar 1.10 89/04/04 SMI; from S5R3 1.10 */
/*
** Skeleton parser driver for yacc output
*/
/*
** yacc user known macros and defines
*/
#define YYERROR goto yyerrlab
#define YYACCEPT { free(yys); free(yyv); return(0); }
#define YYABORT { free(yys); free(yyv); return(1); }
#define YYBACKUP( newtoken, newvalue )\
{\
if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
{\
yyerror( "syntax error - cannot backup" );\
goto yyerrlab;\
}\
yychar = newtoken;\
yystate = *yyps;\
yylval = newvalue;\
goto yynewstate;\
}
#define YYRECOVERING() (!!yyerrflag)
#ifndef YYDEBUG
# define YYDEBUG 1 /* make debugging available */
#endif
/*
** user known globals
*/
int yydebug; /* set to 1 to get debugging */
/*
** driver internal defines
*/
#define YYFLAG (-1000)
/*
** static variables used by the parser
*/
static YYSTYPE *yyv; /* value stack */
static int *yys; /* state stack */
static YYSTYPE *yypv; /* top of value stack */
static int *yyps; /* top of state stack */
static int yystate; /* current state */
static int yytmp; /* extra var (lasts between blocks)*/
int yynerrs; /* number of errors */
int yyerrflag; /* error recovery flag */
int yychar; /* current input token number */
/*
** yyparse - return 0 if worked, 1 if syntax error not recovered from
*/
int
yyparse()
{
register YYSTYPE *yypvt; /* top of value stack for $vars */
unsigned yymaxdepth = YYMAXDEPTH;
/*
** Initialize externals - yyparse may be called more than once
*/
yyv = (YYSTYPE*)malloc(yymaxdepth*sizeof(YYSTYPE));
yys = (int*)malloc(yymaxdepth*sizeof(int));
if (!yyv || !yys)
{
yyerror( "out of memory" );
return(1);
}
yypv = &yyv[-1];
yyps = &yys[-1];
yystate = 0;
yytmp = 0;
yynerrs = 0;
yyerrflag = 0;
yychar = -1;
goto yystack;
{
register YYSTYPE *yy_pv; /* top of value stack */
register int *yy_ps; /* top of state stack */
register int yy_state; /* current state */
register int yy_n; /* internal state number info */
/*
** get globals into registers.
** branch to here only if YYBACKUP was called.
*/
yynewstate:
yy_pv = yypv;
yy_ps = yyps;
yy_state = yystate;
goto yy_newstate;
/*
** get globals into registers.
** either we just started, or we just finished a reduction
*/
yystack:
yy_pv = yypv;
yy_ps = yyps;
yy_state = yystate;
/*
** top of for (;;) loop while no reductions done
*/
yy_stack:
/*
** put a state and value onto the stacks
*/
#if YYDEBUG
/*
** if debugging, look up token value in list of value vs.
** name pairs. 0 and negative (-1) are special values.
** Note: linear search is used since time is not a real
** consideration while debugging.
*/
if ( yydebug )
{
register int yy_i;
(void)printf( "State %d, token ", yy_state );
if ( yychar == 0 )
(void)printf( "end-of-file\n" );
else if ( yychar < 0 )
(void)printf( "-none-\n" );
else
{
for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
yy_i++ )
{
if ( yytoks[yy_i].t_val == yychar )
break;
}
(void)printf( "%s\n", yytoks[yy_i].t_name );
}
}
#endif /* YYDEBUG */
if ( ++yy_ps >= &yys[ yymaxdepth ] ) /* room on stack? */
{
/*
** reallocate and recover. Note that pointers
** have to be reset, or bad things will happen
*/
int yyps_index = (yy_ps - yys);
int yypv_index = (yy_pv - yyv);
int yypvt_index = (yypvt - yyv);
yymaxdepth += YYMAXDEPTH;
yyv = (YYSTYPE*)realloc((char*)yyv,
yymaxdepth * sizeof(YYSTYPE));
yys = (int*)realloc((char*)yys,
yymaxdepth * sizeof(int));
if (!yyv || !yys)
{
yyerror( "yacc stack overflow" );
return(1);
}
yy_ps = yys + yyps_index;
yy_pv = yyv + yypv_index;
yypvt = yyv + yypvt_index;
}
*yy_ps = yy_state;
*++yy_pv = yyval;
/*
** we have a new state - find out what to do
*/
yy_newstate:
if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
goto yydefault; /* simple state */
#if YYDEBUG
/*
** if debugging, need to mark whether new token grabbed
*/
yytmp = yychar < 0;
#endif
if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
yychar = 0; /* reached EOF */
#if YYDEBUG
if ( yydebug && yytmp )
{
register int yy_i;
(void)printf( "Received token " );
if ( yychar == 0 )
(void)printf( "end-of-file\n" );
else if ( yychar < 0 )
(void)printf( "-none-\n" );
else
{
for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
yy_i++ )
{
if ( yytoks[yy_i].t_val == yychar )
break;
}
(void)printf( "%s\n", yytoks[yy_i].t_name );
}
}
#endif /* YYDEBUG */
if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
goto yydefault;
if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar ) /*valid shift*/
{
yychar = -1;
yyval = yylval;
yy_state = yy_n;
if ( yyerrflag > 0 )
yyerrflag--;
goto yy_stack;
}
yydefault:
if ( ( yy_n = yydef[ yy_state ] ) == -2 )
{
#if YYDEBUG
yytmp = yychar < 0;
#endif
if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
yychar = 0; /* reached EOF */
#if YYDEBUG
if ( yydebug && yytmp )
{
register int yy_i;
(void)printf( "Received token " );
if ( yychar == 0 )
(void)printf( "end-of-file\n" );
else if ( yychar < 0 )
(void)printf( "-none-\n" );
else
{
for ( yy_i = 0;
yytoks[yy_i].t_val >= 0;
yy_i++ )
{
if ( yytoks[yy_i].t_val
== yychar )
{
break;
}
}
(void)printf( "%s\n", yytoks[yy_i].t_name );
}
}
#endif /* YYDEBUG */
/*
** look through exception table
*/
{
register int *yyxi = yyexca;
while ( ( *yyxi != -1 ) ||
( yyxi[1] != yy_state ) )
{
yyxi += 2;
}
while ( ( *(yyxi += 2) >= 0 ) &&
( *yyxi != yychar ) )
;
if ( ( yy_n = yyxi[1] ) < 0 )
YYACCEPT;
}
}
/*
** check for syntax error
*/
if ( yy_n == 0 ) /* have an error */
{
/* no worry about speed here! */
switch ( yyerrflag )
{
case 0: /* new error */
yyerror( "syntax error" );
goto skip_init;
yyerrlab:
/*
** get globals into registers.
** we have a user generated syntax type error
*/
yy_pv = yypv;
yy_ps = yyps;
yy_state = yystate;
yynerrs++;
skip_init:
case 1:
case 2: /* incompletely recovered error */
/* try again... */
yyerrflag = 3;
/*
** find state where "error" is a legal
** shift action
*/
while ( yy_ps >= yys )
{
yy_n = yypact[ *yy_ps ] + YYERRCODE;
if ( yy_n >= 0 && yy_n < YYLAST &&
yychk[yyact[yy_n]] == YYERRCODE)
{
/*
** simulate shift of "error"
*/
yy_state = yyact[ yy_n ];
goto yy_stack;
}
/*
** current state has no shift on
** "error", pop stack
*/
#if YYDEBUG
# define _POP_ "Error recovery pops state %d, uncovers state %d\n"
if ( yydebug )
(void)printf( _POP_, *yy_ps,
yy_ps[-1] );
# undef _POP_
#endif
yy_ps--;
yy_pv--;
}
/*
** there is no state on stack with "error" as
** a valid shift. give up.
*/
YYABORT;
case 3: /* no shift yet; eat a token */
#if YYDEBUG
/*
** if debugging, look up token in list of
** pairs. 0 and negative shouldn't occur,
** but since timing doesn't matter when
** debugging, it doesn't hurt to leave the
** tests here.
*/
if ( yydebug )
{
register int yy_i;
(void)printf( "Error recovery discards " );
if ( yychar == 0 )
(void)printf( "token end-of-file\n" );
else if ( yychar < 0 )
(void)printf( "token -none-\n" );
else
{
for ( yy_i = 0;
yytoks[yy_i].t_val >= 0;
yy_i++ )
{
if ( yytoks[yy_i].t_val
== yychar )
{
break;
}
}
(void)printf( "token %s\n",
yytoks[yy_i].t_name );
}
}
#endif /* YYDEBUG */
if ( yychar == 0 ) /* reached EOF.
quit */
YYABORT;
yychar = -1;
goto yy_newstate;
}
}/* end if ( yy_n == 0 ) */
/*
** reduction by production yy_n
** put stack tops, etc. so things right after switch
*/
#if YYDEBUG
/*
** if debugging, print the string that is the user's
** specification of the reduction which is just about
** to be done.
*/
if ( yydebug )
(void)printf( "Reduce by (%d) \"%s\"\n",
yy_n, yyreds[ yy_n ] );
#endif
yytmp = yy_n; /* value to switch
over */
yypvt = yy_pv; /* $vars top of
value stack */
/*
** Look in goto table for next state
** Sorry about using yy_state here as temporary
** register variable, but why not, if it works...
** If yyr2[ yy_n ] doesn't have the low order bit
** set, then there is no action to be done for
** this reduction. So, no saving & unsaving of
** registers done. The only difference between the
** code just after the if and the body of the if is
** the goto yy_stack in the body. This way the test
** can be made before the choice of what to do is needed.
*/
{
/* length of production doubled with extra bit */
register int yy_len = yyr2[ yy_n ];
if ( !( yy_len & 01 ) )
{
yy_len >>= 1;
yyval = ( yy_pv -= yy_len )[1];
/* $$ = $1 */
yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
*( yy_ps -= yy_len ) + 1;
if ( yy_state >= YYLAST ||
yychk[ yy_state =
yyact[ yy_state ] ] != -yy_n )
{
yy_state = yyact[ yypgo[ yy_n ] ];
}
goto yy_stack;
}
yy_len >>= 1;
yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */
yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
*( yy_ps -= yy_len ) + 1;
if ( yy_state >= YYLAST ||
yychk[ yy_state = yyact[ yy_state ] ]
!= -yy_n )
{
yy_state = yyact[ yypgo[ yy_n ] ];
}
}
/* save until reenter driver code */
yystate = yy_state;
yyps = yy_ps;
yypv = yy_pv;
}
/*
** code supplied by user is placed in this switch
*/
switch( yytmp )
{
case 1:
{ /* Empty */
YYACCEPT
} break;
case 2:
{
ParseResult = yypvt[-1].Nval;
YYACCEPT
} break;
case 3:
{ /* Include a file of expressions */
/* Read in the file as a giant string, and insert */
/* it before the what's left of the current expression. */
CHAR *SaveExpression, *NewExpression, c, *s;
FILE *expfile;
INT i, slen, explen, needed_size;
if( !( expfile = VIfopen(id) ) )
/* Should use DV standard error reporting using:
VEerrsignal( V_SEVERE, V_FILE_OPEN_ERROR, id, "FDSeval" ); */
(VOID)S_FPRINTF( stderr, "Couldn't open file: %s\n", id );
else
{
/* Make a copy of what's left of the expression */
/* to add it to the end of what we include. */
SaveExpression = VIstrclone( (char*)expression );
/* Read in the characters from the include file, */
/* making sure to grow the string as necessary */
i = 0;
explen = 512;
s = NewExpression = S_ALLOC( explen * (LONG)sizeof(CHAR) );
while( EOF != ( c = getc(expfile) ) )
{
if( i >= explen )
{ /* We ran out of room */
s = S_ALLOC( ( 512 + explen ) * (LONG)sizeof(CHAR) );
cpybuf( s, NewExpression, explen );
S_FREE( (ADDRESS)NewExpression );
NewExpression = s;
s = &NewExpression[explen];
explen += 512;
}
*s++ = c;
i++;
}
(VOID)S_FCLOSE( expfile );
/* Add a ';' and the current expression to the end */
/* making sure there is enough room */
slen = S_STRLEN(SaveExpression);
needed_size = i + 2 + slen;
if( needed_size >= explen )
{ /* Need more room */
s = S_ALLOC( needed_size * (LONG)sizeof(CHAR) );
cpybuf( s, NewExpression, i );
S_FREE( (ADDRESS)NewExpression );
NewExpression = s;
s = &NewExpression[i];
}
*s++ = ';';
cpybuf( s, SaveExpression, slen+1 );
S_FREE( (ADDRESS)ExpStart );
S_FREE( (ADDRESS)SaveExpression );
ExpStart = NewExpression;
expression = ExpStart;
}
YYACCEPT
} break;
case 4:
{ /* Error in expression; create a zero generator */
ParseResult = PTNcreate( number,(FCN)0,(NODE*)0,
(NODE*)0,(NODE*)0 );
YYACCEPT
} break;
case 5:
{ yyval.Sval = ConvertNameToSymbol(id); } break;
case 6:
{ yyval.ival = CurrentArgIndex; } break;
case 7:
{ yyval.Nval = PTNcreate( number,(FCN)0,(NODE*)0,(NODE*)0,(NODE*)0 ); } break;
case 8:
{
/* This is a symbol in the expression that means that */
/* we are to get the value from outside the expression */
/* parser's environment. Save the index of the argument */
/* so that when we later evaluate the expression, we can */
/* bind the index to some value or data source */
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)readvar,
(NODE*)0,(NODE*)0,(NODE*)0 );
/* Set up the parameter field for readvar */
yyval.Nval->params = (ADDRESS)yypvt[-0].ival; /* Save */
/* argument */
/* index for later */
yyval.Nval->FreeParams = NULL;
} break;
case 9:
{
/* Add symbol to data area */
daAddEntry( CurrentParams->data_area, yypvt[-2].Sval );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)assign,
(NODE*)yypvt[-0].Nval,(NODE*)0,(NODE*)0 );
/* Set up the parameter field for assign */
yyval.Nval->params =
(ADDRESS)daGetDatumAddress( CurrentParams->data_area,
yypvt[-2].Sval );
yyval.Nval->FreeParams = NULL;
} break;
case 10:
{ /* Write the expression out to a data source variable */
/* if the destination argument is a data source variable */
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)assign_to_dsv,
(NODE*)yypvt[-0].Nval,(NODE*)0,(NODE*)0 );
/* Set up parameter field for assign_to_dsv */
yyval.Nval->params = (ADDRESS)yypvt[-2].ival; /* Save index */
/* of arg to */
/* write to. */
yyval.Nval->FreeParams = NULL;
} break;
case 11:
{ yyval.Nval = PTNcreate( (DOUBLE)0,cond,yypvt[-4].Nval,
yypvt[-2].Nval,yypvt[-0].Nval ); } break;
case 12:
{
GetFcn(yypvt[-2].Sval, &fcn, &numargs);
if( fcn && numargs == 0 )
yyval.Nval = PTNcreate( (DOUBLE)0,fcn,(NODE*)0,
(NODE*)0,(NODE*)0 );
else
{
if( fcn == 0 )
ErrFcnUndefined( yypvt[-2].Sval );
else
ErrArgMismatch( yypvt[-2].Sval, numargs, 0 );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
(NODE*)0,(NODE*)0,(NODE*)0 );
}
} break;
case 13:
{
GetFcn(yypvt[-3].Sval, &fcn, &numargs);
if( fcn && numargs == 1 )
yyval.Nval = PTNcreate( (DOUBLE)0,fcn,
yypvt[-1].Nval,(NODE*)0,(NODE*)0 );
else
{
if( fcn == 0 )
ErrFcnUndefined( yypvt[-3].Sval );
else
ErrArgMismatch( yypvt[-3].Sval, numargs, 1 );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
(NODE*)0,(NODE*)0,(NODE*)0 );
}
} break;
case 14:
{
GetFcn(yypvt[-5].Sval, &fcn, &numargs);
if( fcn && numargs == 2 )
yyval.Nval = PTNcreate( (DOUBLE)0,fcn,yypvt[-3].Nval,
yypvt[-1].Nval,(NODE*)0 );
else
{
if( fcn == 0 )
ErrFcnUndefined( yypvt[-5].Sval );
else
ErrArgMismatch( yypvt[-5].Sval, numargs, 2 );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
(NODE*)0,(NODE*)0,(NODE*)0 );
}
} break;
case 15:
{
GetFcn(yypvt[-7].Sval, &fcn, &numargs);
if( fcn && numargs == 3 )
yyval.Nval = PTNcreate( (DOUBLE)0,fcn,yypvt[-5].Nval,
yypvt[-3].Nval,yypvt[-1].Nval );
else
{
if( fcn == 0 )
ErrFcnUndefined( yypvt[-7].Sval );
else
ErrArgMismatch( yypvt[-7].Sval, numargs, 3 );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)0,
(NODE*)0,(NODE*)0,(NODE*)0 );
}
} break;
case 16:
{
/* Add symbol to data area */
daAddEntry( CurrentParams->data_area, yypvt[-0].Sval );
yyval.Nval = PTNcreate( (DOUBLE)0,(FCN)readsym,
(NODE*)0,(NODE*)0,(NODE*)0 );
/* Set up the parameter field for readsym */
yyval.Nval->params =
(ADDRESS)daGetDatumAddress( CurrentParams->data_area,
yypvt[-0].Sval );
yyval.Nval->FreeParams = NULL;
} break;
case 17:
{ yyval.Nval = PTNcreate( (DOUBLE)0,NEtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 18:
{ yyval.Nval = PTNcreate( (DOUBLE)0,EQtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 19:
{ yyval.Nval = PTNcreate( (DOUBLE)0,GEtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 20:
{ yyval.Nval = PTNcreate( (DOUBLE)0,GTtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 21:
{ yyval.Nval = PTNcreate( (DOUBLE)0,LEtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 22:
{ yyval.Nval = PTNcreate( (DOUBLE)0,LTtest,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 23:
{ yyval.Nval = PTNcreate( (DOUBLE)0,add,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 24:
{ yyval.Nval = PTNcreate( (DOUBLE)0,minus,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 25:
{ yyval.Nval = PTNcreate( (DOUBLE)0,mult,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 26:
{ yyval.Nval = PTNcreate( (DOUBLE)0,divide,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 27:
{ yyval.Nval = PTNcreate( (DOUBLE)0,neg,yypvt[-0].Nval,(NODE*)0,
(NODE*)0 ); } break;
case 28:
{ yyval.Nval = PTNcreate( (DOUBLE)0,pow,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 29:
{ yyval.Nval = PTNcreate( (DOUBLE)0,mod,yypvt[-2].Nval,
yypvt[-0].Nval,(NODE*)0 ); } break;
case 30:
{ yyval.Nval = yypvt[-1].Nval; } break;
}
goto yystack; /* reset registers in driver code */
}